/*
 * Copyright © 2017 CHANGLEI. All rights reserved.
 */

package com.daimajia.slider.library.SliderTypes;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import net.izhuo.app.library.R;

import java.io.File;

/**
 * When you want to make your own slider view, you must extends from this class.
 * IBaseSliderView provides some useful methods. I provide two example:
 * {@link IDefaultSliderView} and
 * {@link ITextSliderView} if you want to
 * show progressbar, you just need to set a progressbar id as @+id/loading_bar.
 */
public abstract class IBaseSliderView {

	protected Context mContext;

	private Bundle mBundle;

	/**
	 * Error place holder image.
	 */
	private int mErrorPlaceHolderRes;

	/**
	 * Empty imageView placeholder.
	 */
	private int mEmptyPlaceHolderRes;

	private String mUrl;
	private File mFile;
	private int mRes;

	protected OnSliderClickListener mOnSliderClickListener;

	private boolean mErrorDisappear;

	private ImageLoadListener mLoadListener;

	private String mDescription;

	private Picasso mPicasso;

	/**
	 * Scale type of the image.
	 */
	private ScaleType mScaleType = ScaleType.Fit;

	public enum ScaleType {
		CenterCrop, CenterInside, Fit, FitCenterCrop
	}

	protected IBaseSliderView(Context context) {
		mContext = context;
	}

	/**
	 * the placeholder image when loading image from url or file.
	 * 
	 * @param resId
	 *            Image resource id
	 * @return
	 */
	public IBaseSliderView empty(int resId) {
		mEmptyPlaceHolderRes = resId;
		return this;
	}

	/**
	 * determine whether remove the image which failed to download or load from
	 * file
	 * 
	 * @param disappear
	 * @return
	 */
	public IBaseSliderView errorDisappear(boolean disappear) {
		mErrorDisappear = disappear;
		return this;
	}

	/**
	 * if you set errorDisappear false, this will set a error placeholder image.
	 * 
	 * @param resId
	 *            image resource id
	 * @return
	 */
	public IBaseSliderView error(int resId) {
		mErrorPlaceHolderRes = resId;
		return this;
	}

	/**
	 * the description of a slider image.
	 * 
	 * @param description
	 * @return
	 */
	public IBaseSliderView description(String description) {
		mDescription = description;
		return this;
	}

	/**
	 * set a url as a image that preparing to load
	 * 
	 * @param url
	 * @return
	 */
	public IBaseSliderView image(String url) {
		if (mFile != null || mRes != 0) {
			throw new IllegalStateException("Call multi image function,"
					+ "you only have permission to call it once");
		}
		mUrl = url;
		return this;
	}

	/**
	 * set a file as a image that will to load
	 * 
	 * @param file
	 * @return
	 */
	public IBaseSliderView image(File file) {
		if (mUrl != null || mRes != 0) {
			throw new IllegalStateException("Call multi image function,"
					+ "you only have permission to call it once");
		}
		mFile = file;
		return this;
	}

	public IBaseSliderView image(int res) {
		if (mUrl != null || mFile != null) {
			throw new IllegalStateException("Call multi image function,"
					+ "you only have permission to call it once");
		}
		mRes = res;
		return this;
	}

	/**
	 * lets users add a bundle of additional information
	 * 
	 * @param bundle
	 * @return
	 */
	public IBaseSliderView bundle(Bundle bundle) {
		mBundle = bundle;
		return this;
	}

	public String getUrl() {
		return mUrl;
	}

	public boolean isErrorDisappear() {
		return mErrorDisappear;
	}

	public int getEmpty() {
		return mEmptyPlaceHolderRes;
	}

	public int getError() {
		return mErrorPlaceHolderRes;
	}

	public String getDescription() {
		return mDescription;
	}

	public Context getContext() {
		return mContext;
	}

	/**
	 * set a slider image click listener
	 * 
	 * @param l
	 * @return
	 */
	public IBaseSliderView setOnSliderClickListener(OnSliderClickListener l) {
		mOnSliderClickListener = l;
		return this;
	}

	/**
	 * When you want to implement your own slider view, please call this method
	 * in the end in `getView()` method
	 * 
	 * @param v
	 *            the whole view
	 * @param targetImageView
	 *            where to place image
	 */
	@SuppressWarnings("incomplete-switch")
	protected void bindEventAndShow(final View v, ImageView targetImageView) {
		final IBaseSliderView me = this;

		v.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (mOnSliderClickListener != null) {
					mOnSliderClickListener.onSliderClick(me);
				}
			}
		});

		if (targetImageView == null)
			return;

		if (mLoadListener != null) {
			mLoadListener.onStart(me);
		}

		Picasso p = (mPicasso != null) ? mPicasso : Picasso.with(mContext);
		RequestCreator rq = null;
		if (mUrl != null) {
			rq = p.load(mUrl);
		} else if (mFile != null) {
			rq = p.load(mFile);
		} else if (mRes != 0) {
			rq = p.load(mRes);
		} else {
			return;
		}

		if (rq == null) {
			return;
		}

		if (getEmpty() != 0) {
			rq.placeholder(getEmpty());
		}

		if (getError() != 0) {
			rq.error(getError());
		}

		switch (mScaleType) {
		case Fit:
			rq.fit();
			break;
		case CenterCrop:
			rq.fit().centerCrop();
			break;
		case CenterInside:
			rq.fit().centerInside();
			break;
		}

		if (v.findViewById(R.id.box_loading_bar) != null) {
			v.findViewById(R.id.box_loading_bar).setVisibility(
					View.INVISIBLE);
		}
		rq.into(targetImageView, new Callback() {
			@Override
			public void onSuccess() {
				if (v.findViewById(R.id.box_loading_bar) != null) {
					v.findViewById(R.id.box_loading_bar).setVisibility(
							View.INVISIBLE);
				}
			}

			@Override
			public void onError() {
				if (mLoadListener != null) {
					mLoadListener.onEnd(false, me);
				}
				if (v.findViewById(R.id.box_loading_bar) != null) {
					v.findViewById(R.id.box_loading_bar).setVisibility(
							View.INVISIBLE);
				}
			}
		});
	}

	public IBaseSliderView setScaleType(ScaleType type) {
		mScaleType = type;
		return this;
	}

	public ScaleType getScaleType() {
		return mScaleType;
	}

	/**
	 * the extended class have to implement getView(), which is called by the
	 * adapter, every extended class response to render their own view.
	 * 
	 * @return
	 */
	public abstract View getView();

	/**
	 * set a listener to get a message , if load error.
	 * 
	 * @param l
	 */
	public void setOnImageLoadListener(ImageLoadListener l) {
		mLoadListener = l;
	}

	public interface OnSliderClickListener {
		public void onSliderClick(IBaseSliderView slider);
	}

	/**
	 * when you have some extra information, please put it in this bundle.
	 * 
	 * @return
	 */
	public Bundle getBundle() {
		return mBundle;
	}

	public interface ImageLoadListener {
		public void onStart(IBaseSliderView target);

		public void onEnd(boolean result, IBaseSliderView target);
	}

	/**
	 * Get the last instance set via setPicasso(), or null if no user provided
	 * instance was set
	 *
	 * @return The current user-provided Picasso instance, or null if none
	 */
	public Picasso getPicasso() {
		return mPicasso;
	}

	/**
	 * Provide a Picasso instance to use when loading pictures, this is useful
	 * if you have a particular HTTP cache you would like to share.
	 *
	 * @param picasso
	 *            The Picasso instance to use, may be null to let the system use
	 *            the default instance
	 */
	public void setPicasso(Picasso picasso) {
		mPicasso = picasso;
	}
}
